#include "itemtreemodel.h"


#include <QDebug>


ItemTreeModel::ItemTreeModel(QObject *parent) :
    QAbstractItemModel(parent)
{
}


ItemTreeModel::ItemTreeModel(AbstractModelItem *root, QObject *parent) :
    QAbstractItemModel(parent)
{
    m_root = root;
}


AbstractModelItem *ItemTreeModel::itemFromIndex(const QModelIndex &index)
{
    if (!index.isValid()) return 0;

    return reinterpret_cast<AbstractModelItem*>(index.internalPointer());
}


void ItemTreeModel::setRoot(AbstractModelItem *root)
{
    emit layoutAboutToBeChanged();

    beginResetModel();
    m_root = root;
    endResetModel();

    emit layoutChanged();
}


AbstractModelItem *ItemTreeModel::root() const
{
    return m_root;
}


QModelIndex ItemTreeModel::index(int row, int column, const QModelIndex &parent) const
{
    if (row < 0 || !hasIndex(row, column, parent)) return QModelIndex();

    AbstractModelItem* item = m_root;
    if (parent.isValid())
    {
        item = itemFromIndex(parent);
    }

    if (!item)
    {
        return QModelIndex();
    }

    QList<AbstractModelItem*> childItems = item->childItems();
    if (row >= childItems.count())
    {
        qDebug() << Q_FUNC_INFO << "Row is too big!";
        return QModelIndex();
    }

    return createIndex(row, column, childItems.at(row));
}


QModelIndex ItemTreeModel::parent(const QModelIndex &child) const
{
    if (!child.isValid()) return QModelIndex();

    AbstractModelItem* childItem = itemFromIndex(child);
    if (!childItem) return QModelIndex();

    AbstractModelItem* item = qobject_cast<AbstractModelItem*>(childItem->parent());
    if (!item) return QModelIndex();

    AbstractModelItem* parentItem = qobject_cast<AbstractModelItem*>(item->parent());
    if (!parentItem) return QModelIndex();

    QList<AbstractModelItem*> siblingData = parentItem->childItems();
    if (!siblingData.contains(item)) return QModelIndex();

    return createIndex(siblingData.indexOf(item), 0, item);
}


int ItemTreeModel::rowCount(const QModelIndex &parent) const
{
    AbstractModelItem* parentItem = itemFromIndex(parent);
    if (!parentItem) parentItem = m_root;
    if (!parentItem)
    {
        return 0;
    }

    return parentItem->childItems().count();
}


int ItemTreeModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    if (m_root.isNull()) return 0;
    int ret = 0;
    foreach (const AbstractModelItem* item, m_root->findChildren<const AbstractModelItem*>())
    {
        if (!item) continue;

        int fields = item->fieldCount();
        if (fields > ret) ret = fields;
    }

//    qDebug() << Q_FUNC_INFO << "-" << ret;
    return ret;
}


QVariant ItemTreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) return QVariant();

    AbstractModelItem* item = itemFromIndex(index);
    if (!item) return QVariant();

    switch (role)
    {
    case Role_OBJECT_NAME:
        return item->objectName();

    default:
        break;
    }

    return item->value(index.column(), role);
}


bool ItemTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid())
    {
        return false;
    }

    AbstractModelItem* item = itemFromIndex(index);

    if (!item || !item->setValue(index.column(), value, role))
    {
        return false;
    }

    emit dataChanged(index, index);

    return true;
}

